#pragma once
#include <filesystem>
#include <map>
#include <set>
#include <iostream>
#include <fstream>
#include <crossguid/guid.hpp>
#include "AssetObject.h"
#include <memory>

class AssetManager
{
public:
	inline static AssetManager& Get()
	{
		static AssetManager ins;
		return ins;
	}

	// default ".."
	const std::filesystem::path& GetRootPath();

	// empty xg::Guid is root
	const std::map<xg::Guid, std::set<xg::Guid>>& GetAssetTree() const;

	const std::filesystem::path& Guid2Path(const xg::Guid& g)const;

	xg::Guid Path2Guid(const  std::filesystem::path& path)const;

	std::filesystem::path Asset2Path(const YXX_AS::AssetObject& obj)const;

	template<typename Asset>
	std::shared_ptr<Asset> Guid2Asset(const xg::Guid& g);
	std::shared_ptr<YXX_AS::AssetObject> Guid2Asset(const xg::Guid& g);
	// generate meta,map of path2guid and guid2path
	xg::Guid ImportAsset(const std::filesystem::path& path);
	

	// relative dir
	void ImportAssetRecursively(const std::filesystem::path& directory);
	template<typename Asset>
	std::shared_ptr<Asset> LoadAsset(const std::filesystem::path& path);
	std::shared_ptr<YXX_AS::AssetObject> LoadAsset(const std::filesystem::path& path);
private:
	class Impl;
	Impl* pImpl;
	AssetManager();
	~AssetManager();
};
template<typename Asset>
std::shared_ptr<Asset> AssetManager::LoadAsset(const std::filesystem::path& path)
{
	static_assert(std::is_base_of_v<YXX_AS::AssetObject, Asset>);
	return std::static_pointer_cast<Asset>(LoadAsset(path));
}
template<typename Asset>
std::shared_ptr<Asset> AssetManager::Guid2Asset(const xg::Guid& g)
{
	static_assert(std::is_base_of_v<YXX_AS::AssetObject, Asset>);
	return std::dynamic_pointer_cast<Asset>(Guid2Asset(g));
}